package com.ibm.risk.irmp.common.utils;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class RandomCaptchaUtil {
    private static final Logger log = LoggerFactory.getLogger(RandomCaptchaUtil.class);

    public static final String RANDOM_CODE_KEY = "RANDOM_VALIDATE_CODE_KEY";//放到session中的key
    public static final String RANDOM_CODE_KEY_CREATED_TIME = "RANDOM_VALIDATE_CODE_KEY_CREATED_TIME";//放到session中的key
    //过期时间秒
    public static final Integer RANDOM_CODE_KEY_EXPIRE = 180;
    //随机产生只有数字的字符串 private String
    //private static String randString = "0123456789";
    //private static String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串
    //private static String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串
    private static int width = 95;// 图片宽
    //随机产生数字与字母组合的字符串
    private static String randString = "0123456789ABCDEFGHJKLMNPQRSTUVWXY";
    private static int height = 25;// 图片高
    private static int lineSize = 40;// 干扰线数量
    private static int stringNum = 4;// 随机产生字符数量

    private static SecureRandom random;

    static {
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException e) {
            log.error("Error to get SecureRandom.getInstance(\"SHA1PRNG\");", e);
        }
    }

    /**
     * 获得字体
     */
    private static Font getFont() {
        return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
    }

    /**
     * 获得颜色
     */
    private static Color getRandColor(int fc, int bc) {
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + SecureRandomUtil.nextInt(bc - fc - 16);
        int g = fc + SecureRandomUtil.nextInt(bc - fc - 14);
        int b = fc + SecureRandomUtil.nextInt(bc - fc - 18);
        return new Color(r, g, b);
    }

    /**
     * 生成随机图片
     */
    public static String generateCaptcha(HttpServletRequest request, HttpServletResponse response) {
//        HttpSession session = request.getSession();
        // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
        g.fillRect(0, 0, width, height);//图片大小
        g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//字体大小
        g.setColor(getRandColor(110, 133));//字体颜色
        // 绘制干扰线
        for (int i = 0; i <= lineSize; i++) {
            drowLine(g);
        }
        // 绘制随机字符
        String randomString = "";
        for (int i = 1; i <= stringNum; i++) {
            randomString = drowString(g, randomString, i);
        }
        //将生成的随机字符串保存到session中
//        session.removeAttribute(RANDOM_CODE_KEY);
//        session.setAttribute(RANDOM_CODE_KEY, randomString);
//        session.setAttribute(RANDOM_CODE_KEY_CREATED_TIME, Long.valueOf(System.currentTimeMillis()));
        g.dispose();
        try {
            // 将内存中的图片通过流动形式输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            log.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);
        }
        return randomString;
    }

    /**
     * 绘制字符串
     */
    private static String drowString(Graphics g, String randomString, int i) {
        g.setFont(getFont());
        g.setColor(new Color(SecureRandomUtil.nextInt(101), SecureRandomUtil.nextInt(111), SecureRandomUtil.nextInt(121)));
        String rand = String.valueOf(getRandomString(SecureRandomUtil.nextInt(randString.length())));
        randomString += rand;
        g.translate(SecureRandomUtil.nextInt(3), SecureRandomUtil.nextInt(3));
        g.drawString(rand, 13 * i, 16);
        return randomString;
    }

    /**
     * 绘制干扰线
     */
    private static void drowLine(Graphics g) {
        int x = SecureRandomUtil.nextInt(width);
        int y = SecureRandomUtil.nextInt(height);
        int xl = SecureRandomUtil.nextInt(13);
        int yl = SecureRandomUtil.nextInt(15);
        g.drawLine(x, y, x + xl, y + yl);
    }

    /**
     * 获取随机的字符
     */
    public static String getRandomString(int num) {
        return String.valueOf(randString.charAt(num));
    }

    /*
     * 检查验证码：
     * 	1）验证验证码是否正确
     * 	2）验证验证码生成时间不大于 RANDOM_CODE_KEY_EXPIRE 秒数
     */
    public static boolean verify(HttpServletRequest request, HttpServletResponse response) {
        try {
            String inputCaptcha = request.getParameter("captcha");
            String captchaInSession = (String) request.getAttribute(RANDOM_CODE_KEY);
            if (StringUtils.isEmpty(inputCaptcha)) {
                inputCaptcha = (String) request.getAttribute("captcha");
            }
            if (StringUtils.equalsIgnoreCase(inputCaptcha, captchaInSession)) {
                long createdTime = (long) request.getAttribute(RANDOM_CODE_KEY_CREATED_TIME);
                if (System.currentTimeMillis() - createdTime <= RANDOM_CODE_KEY_EXPIRE * 1000) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("验证码校验失败", e);
        }
        return false;
    }
}
